import { Graph } from '@antv/x6/lib/index'
// import { saveAs } from 'file-saver'
import ShapeUtil from './shapeUtil'
import { getGraphNodes, saveCustomNodeTemplate } from '@/api/draw.js'
import ConfigUtil from './configUtil'

export default {
  // 加载自定义节点
  loadCustomizeNodes(component) {
    component.$store.commit('clearRegisterNodes')
    getGraphNodes().then(response => {
      const nodes = response.data
      if (nodes.length === 0) {
        return
      }
      for (const node of nodes) {
        // 注册节点
        const config = JSON.parse(node.content)
        this.registerNode2Graph(component, node.name, config)
      }
    })
  },

  // 向图形系统中注册节点
  registerNode2Graph(component, shapeName, config) {
    Graph.unregisterNode(shapeName)
    // 注册节点
    Graph.registerNode(shapeName, config, true)
    component.$store.commit('appendRegisterNode', {
      shapeName: shapeName,
      config: config
    })
  },

  // 加载模板内容，产生自定义节点
  loadTemplateFile(component, file) {
    var self = this

    const reader = new FileReader()
    reader.readAsText(file)
    reader.onload = function(e) {
      try {
        var templateObj = JSON.parse(this.result)
        for (const template of templateObj) {
          // 注册节点
          self.registerNode2Graph(component, template.name, template)
        }
      } catch (e) {
        component.$alert('文件内容转换为json失败,请选择正确的文件!')
        console.log('loadTemplateFile failed: ', e)
      }
    }
  },

  // 保存自定义节点
  saveTemplateFile(component, config) {
    // 获取系统中已注册的自定义节点
    // const registerNodes = component.$store.state.nodeModule.registerNodes
    var text = JSON.stringify(config, null, '\t')
    saveCustomNodeTemplate(text).then(response => {
      component.$message({
        title: '保存文件成功'
      })
    })
    // var blob = new Blob([text], { type: 'text/plaincharset=utf-8' })

    // saveAs(blob, 'template.json')
  },

  // 节点属性中需要忽略的属性值
  ignoredAttrs: ['selector'],

  isIgnoredAttr(attr) {
    return this.ignoredAttrs.indexOf(attr) !== -1
  },

  // 注册自定义节点
  registerCustomNode(component, formConfig, node) {
    const nodeSize = node.size()
    const childNodes = node.getChildren()
    const config = {}
    config.shape = formConfig.nodeName
    config.width = nodeSize.width
    config.height = nodeSize.height
    config.markup = this.trans2Markup(childNodes)
    config.attrs = this.trans2Attrs(childNodes, nodeSize)
    const ports = this.trans2Ports(childNodes)
    if (ports.items && ports.items.length > 0) {
      config.ports = ports
    }

    // 设置节点的自定义属性
    config.data = {}
    config.data.group = formConfig.nodeGroup
    config.data.metaType = formConfig.nodeType
    config.data.metaName = ConfigUtil.getMetaTypeName(formConfig.nodeType)
    config.data.desc = formConfig.nodeDesc

    try {
      this.registerNode2Graph(component, formConfig.nodeName, config)

      // 保存自定义节点
      this.saveTemplateFile(component, config)
    } catch (e) {
      console.log('registerNode 注册节点时发生错误: ', e)
    }
  },

  // 计算节点的尺寸
  getNodeSize(nodes) {
    let minX = Number.POSITIVE_INFINITY
    let maxX = Number.NEGATIVE_INFINITY
    let minY = Number.POSITIVE_INFINITY
    let maxY = Number.NEGATIVE_INFINITY
    for (const node of nodes) {
      const position = node.position()
      const size = node.size()
      minX = Math.min(minX, position.x)
      maxX = Math.max(maxX, position.x + size.width)

      minY = Math.min(minY, position.y)
      maxY = Math.max(maxY, position.y + size.height)
    }
    return {
      minX: minX,
      minY: minY,
      width: maxX - minX,
      height: maxY - minY
    }
  },

  // 转换节点的markup属性
  trans2Markup(nodes) {
    if (nodes.length === 0) {
      return []
    }
    const markup = []
    nodes.forEach((node) => {
      markup.push({
        tagName: node.shape,
        selector: node.data.selector
      })
    })
    return markup
  },

  // 转换节点的attrs属性
  trans2Attrs(nodes, nodeSize) {
    if (nodes.length === 0) {
      return {}
    }
    const attrs = {}
    nodes.forEach((node) => {
      const size = node.size()
      const position = node.position({ relative: true })

      var nodeAttrs = node.getAttrs()
      const selector = node.data.selector

      if (node.data.isPort) {
        return
      }

      attrs[selector] = {}
      for (var attr in nodeAttrs.body) {
        if (!this.isIgnoredAttr(attr)) {
          attrs[selector][attr] = nodeAttrs.body[attr]
        }
      }

      // 获取shape中的属性，用于覆盖body中不存在的属性
      if (!attrs[selector].fill) {
        attrs[selector].fill = ShapeUtil.getFillAttr(node)
      }
      if (!attrs[selector].stroke) {
        attrs[selector].stroke = ShapeUtil.getStrokeAttr(node)
      }
      if (!attrs[selector].strokeWidth) {
        attrs[selector].strokeWidth = ShapeUtil.getStrokeWidthAttr(node)
      }

      // 覆盖从body中继承的部分属性
      if (node.shape === 'rect') {
        attrs[selector].refWidth = size.width / nodeSize.width
        attrs[selector].refHeight = size.height / nodeSize.height
        attrs[selector].refX = position.x
        attrs[selector].refY = position.y
      }

      if (node.shape === 'circle') {
        const radius = size.width / 2
        attrs[selector].refCx = position.x + radius - nodeSize.width
        attrs[selector].refCy = position.y + radius - nodeSize.height
        attrs[selector].r = radius
        delete attrs[selector].refR
      }

      // 覆盖polygon和polyline中的部分属性
      if (node.shape === 'polygon' || node.shape === 'polyline') {
        attrs[selector].ref = selector + '-ref'
        attrs[selector].refX = 0
        attrs[selector].refY = 0
      }
    })
    return attrs
  },

  // 转换节点的ports属性
  trans2Ports(nodes) {
    if (nodes.length === 0) {
      return {}
    }
    const ports = {}
    ports.groups = {
      group: {
        position: 'absolute',
        attrs: {
          circle: {
            r: 2,
            magnet: true,
            stroke: '#31d0c6',
            strokeWidth: 1,
            fill: '#fff',
            style: {
              visibility: 'hidden'
            }
          }
        }
      }
    }
    ports.items = []
    nodes.forEach((node) => {
      if (!node.data.isPort) {
        return
      }
      const position = node.position({ relative: true })
      const size = node.size()

      ports.items.push({
        group: 'group',
        args: {
          x: position.x + size.width / 2,
          y: position.y + size.width / 2
        }
      })
    })

    return ports
  }
}
